<?php
/**
 * Класс предназначен для работы с сессиями
 *
 */
class User_Session {
  private $ascii_session_id;          //Сгенерированный PHP идентификатор сеанса (32 символа)
  private $ID_user_session;       //Идентификатор сеанса, используемый в базе данных (нужен для связи сущностей в базе данных)
  private $logged_in;               //[bool] Логическая переменная, определяющая активность сеанса
  private $ID_user;                 //Идентификатор (берется из БД) текущего зарегистрированного пользователя
  private $sessionTimeout = 60000000;   //Время ожидания. Если период между запросами превышает эту величину, сеанс прерывается.
  private $sessionLifespan = 36000000; //Максимальный срок действия сеанса
  private $objUser;
  public static $objSession;

  /**
   * Конструктор. Переопределяет ф-ции для работы с сессией
   *
   */
  private function __construct() {
    Service_Debug::setDebug();
    session_set_save_handler(
      array(&$this, '_session_open_method'),
      array(&$this, '_session_close_method'),
      array(&$this, '_session_read_method'),
      array(&$this, '_session_write_method'),
      array(&$this, '_session_destroy_method'),
      array(&$this, '_session_gc_method')
    );
    //Проверка cookie: переданы ли эти данные и корректны ли они
    if (isset($_COOKIE["PHPSESSID"]) && $_COOKIE["PHPSESSID"]) {
      // Проверка сроков давности для безопасности
      $this->ascii_session_id = $_COOKIE["PHPSESSID"];//Идентификатор сеанса

      $arResult = $this->_baseGetCorrectSessionsWithAscii();
      if (sizeof($arResult) == 0) { // Если в базе нет такого идентификатора сесии или срок действия сеанса истек или используется другой пользовательский агент или ( с последнего обращения к странице прошло больше времени, чем время ожидания или не было обращений к странице)
        $failed = 1; // Установка флага failed
        // Удаление из базы данных - периодическая сборка мусора
        // Удаляем сессию с соответствующим ascii_session_id и сессии, у которых истек максимальный срок действия сеанаса
        //$this->_baseDeleteIncorrectSessionsAndAsciiSess();
        // Очищаем переменные сеанса
        // Удаляем все переменные сесии, для которых не осталось соответствующей сессии
        //$this->_baseDeleteIncorrectSessionsVariables();
        
        //unset($_COOKIE["PHPSESSID"]); // Удаление идентификатора в cookie
      }
    }
    session_set_cookie_params($this->sessionLifespan, '/', '.' . DOMAIN); // Установка времени жизни данных cookie
    session_start();//Вызовется сначала _session_open,  потом _session_read
  }

  /**
   * Функция обеспечивает работу шаблона Singleton
   * Благодаря ей у нас всегда будет только один объект пользовательской сессии
   *
   * @return object - объект сессии
   */
  static public function instance() {
    Service_Debug::setDebug();
    if (!isset(self::$objSession)) {
      self::$objSession = new User_Session();
    }
    return self::$objSession;
  }

  /**
   * Позволяет определить факт нового обращения к странице
   * Должен вызываться на любой странице в которой используется класс сеанса,
   * сразу же после его инстанцирования
   *
   */
  public function impress() {
    Service_Debug::setDebug();
    if ($this->ID_user_session) {//Если имеется идентификатор сеанса, используемый в базе, то
    	if ($this->isLoggedIn()) {
    		$lastImpression = $this->_baseGetLastImpression();
      }
    	$this->_baseUpdatelast_impression();//Обновляем время последнего обращения
    }
  }

  /**
   * Проверка регистрации пользователя в рамках сеанса
   *
   * @return bool - залогинен или нет
   */
  public function isLoggedIn() {
  	return($this->logged_in);
  }

  /**
   * Получение идентификатора пользователя
   *
   * @return int - ID пользователя
   */
  public function getUserId() {
    if ($this->logged_in) { //Если сеанс активен
      return ($this->ID_user);
    }
    else return false;
  }


  /**
   * Получение объекта пользователя
   *
   * @return object - объект пользователя
   */
  public function getUser() {
    if (!isset($this->objUser)) {
      if ($this->logged_in) $this->objUser =  new User_User($this->getUserId());
      else $this->objUser =  new User_User();
    }
    return $this->objUser;
  }

  /**
   * Получение идентификатора сессии
   *
   * @return int - ID пользователя
   */
  public function getUserSessionId() {
      return $this->ID_user_session;
  }

  /**
   * Возвращает 32-символьный идентификатор сеанса PHP
   *
   * @return string - 32-символьный идентификатор сеанса PHP
   */
  public function getSessionIdentifier() {
    return($this->ascii_session_id);
  }

  /**
   * Успешный вход в систему (подразумевается вызов после проверки логина и пароля)
   * 
   * @param integer $userId
   * @param bool $saveMe
   */
	public function signInSuccess($userId, $saveMe = true) {
		Service_Debug::setDebug();
		if (!$userId) return false;
		$this->ID_user = $userId;//Запоминаем id пользователя
    $this->logged_in = true;//Активируем сеанс
    $this->_baseLogInSession();
    return true;
	}
  


  /**
   * Функция выхода
   * Возвращает true, если вышли. false, если сеанс не был активен
   * @param bool $onlyServerCookies - если выставить в true, то Куки не будут сохраняться у клиента. Будут сохраняться только в массиве $_COOKIE на сервере
   *
   * @return bool - Вышли или нет
   */
  public function logOut($onlyServerCookies = false) {
    Service_Debug::setDebug();
    if ($this->logged_in) {//Если сеанс активен
      //Устанавливаем для текущей сессии состоянии НЕ активный сеанс и обнуляем пользователя.
      User_User::setStatus(0, $this->getUserId());
      $this->_baseLogOutSession();
      $this->logged_in = false; //Деактивируем сеанс
      $this->ID_user = 0; //Обнуляем id пользователя
      if (!$onlyServerCookies) {
      	setcookie("SaveMe", null, null, W_ABSPATH, '.' . DOMAIN);
      	setcookie("SaveMe", null, null, W_ABSPATH);
      }
      else $_COOKIE['SaveMe'] = null;
      if (defined('DOMAIN')) {
	      setcookie('fbm_' . FACEBOOK_API, null, null, W_ABSPATH, '.' . DOMAIN);
	      setcookie('fbsr_' . FACEBOOK_API, null, null, W_ABSPATH, '.' . DOMAIN);
      }
      return true;
    }
    else { // Если сеанс НЕ активен
      return false;
    }
  }


  /**
   * Метод переправляет пользователя на другую страницу. При необходимости сохраняет сообщение в переменную сессиии
   *
   * @param string $location
   * @param string $message
   * @param integer $messageType
   */
  public static function moveTo($location, $message = null, $messageType = -1, $saveHtml = false) {
    if ($message) {
      if ($messageType > 0) User_Flash::_set('successMessage', $message, $saveHtml);
      else User_Flash::_set('errorMessage', $message);
    }
    header('HTTP/1.1 301 Moved Permanently');
    header('Location: ' . $location);
    exit();
  }

  /**
   * Метод переправляет пользователя на другую страницу. В том, случае, если пользователь не зарегистрирован
   * В противном случае возвращает идентификатор пользователя
   *
   * @param string $location
   * @param string $message
   * @param integer $messageType
   */
  public static function moveToIfNotRegist($location, $message = null) {
    $objSession = self::instance();
    $userId = $objSession->getUserId();
    if (!$userId) $objSession->moveTo($location, $message);
    return $userId;
  }

/**
 * Эта функция запускается при открытии сессии - сделана на будущее для дополнительных возможных проверок и пр.
 * Получает путь $save_path, по которому должны храниться переменные сеанса и имя файла cookie
 *
 * @param atring $save_path
 * @param string $session_name
 * @return bool
 */
  private function _session_open_method($save_path, $session_name) {
    //Ничего не делаем
    return true;
  }

  /**
   * Эта функция запускается при закрытии сессии
   *
   * @return bool
   */
  public function _session_close_method() {
    //Ничего не делаем
    return true;
  }

  /**
   * Эта функция используется при попытке извлечения переменной из массива $_SESSION
   * Ей передается идентификатор сеанса
   * По умолчанию возвращает сериализованное представление массива $_SESSION, но не в нашем случае, т.к. у нас собственная обработка
   *
   * @param integer $id - ID сеанса
   * @return string - Пустая строка
   */
  private function _session_read_method($id) {
    Service_Debug::setDebug();
    $this->ascii_session_id = $id; //Записываем id сессии
    $failed = 1; //Установка флага failed
    //Проверить наличие данных в базе данных
    //(Есть ли соответствующая текущему id сессия?)
    $arResult = $this->_baseGetSessionById($id);
    if (sizeof($arResult) > 0) { //Если сессия с текущим id существует, то...
      $this->ID_user_session = $arResult[0]["ID_user_session"]; //Запоминаем id сессии из БД
      if ($arResult[0]["logged_in"]==1) { //Если сеанс активен
        $this->logged_in = true; //Активируем сеанс
        $this->ID_user = $arResult[0]["ID_user"]; //Записываем id пользователя
      }
      else { //Если сеанс НЕ активен
        $this->logged_in = false; //Деактивируем сеанс
      }
    }
    else { //Если сессия с текущим id НЕ существует, то...
      $this->logged_in = false; //Деактивируем сеанс
      //Необходимо создать запись в БД
      //Сессия с текущим id, деактивированная, без соответствия пользователя...

      $this->ID_user_session = $this->_baseCreateNewEmptySessionByAscii($id, self::getUserAgent());
    }
    return(""); // Возвращаем пустую строку
  }

/**
 * Эта функция вызывается при попытке модифицировать массив $_SESSION
 * Ей передается идентификатор сеанса + сериализованное представление массива $_SESSION
 * Возвращает true, если все ок.
 * Вызывается даже если переменные сеанса не зарегистрированы, и при первом вызове записывает сгенерированный идентификатор сеанса
 *
 * @param integer $id - ID сеанса
 * @param string $sess_data - Сериализованное представление массива $_SESSION
 * @return bool
 */
  public function _session_write_method($id, $sess_data) {
    return true;
  }

  /**
   * Вызывается при вызове в коде функции session_destroy();
   *
   * @param integer $id - ID сеанса
   */
  private function _session_destroy_method($id) {
    $objDB = Service_Database::instance();
    $objDB->delete('session', array('ascii_session_id' => $id));
  }

  /**
   * Функция сборки мусора.
   * Получает максимальное время жизни данных cookie для текущего сеанса
   * Удаляет любые данные, срок жизни которых превышает заданный
   *
   * @param integer $maxlifetime - Время жизни сеанса
   * @return bool
   */
  private function _session_gc_method($maxlifetime) {
    return true;
  }

  /**
   * Функция работает с БД
   * Функция выбирает из БД все сессии с соответствующим ASCII сессии
   *
   * @return array - Массив с сессией
   */
  private function _baseGetCorrectSessionsWithAscii() {
    Service_Debug::setDebug();
    $objDB = Service_Database::instance();
    $stmt = "SELECT ID_user_session, logged_in FROM `session` WHERE ascii_session_id = '" . $this->ascii_session_id . "' AND ((now() - created) < ' " . $this->sessionLifespan . " seconds') AND user_agent='" . $this->getUserAgent() . "' AND ((now() - last_impression) <= '" . $this->sessionTimeout . " seconds' OR last_impression IS NULL)";
    return $objDB->select($stmt);
  }

  /**
   * Проверяет, залогинен ли пользователь с соответствующим $asciiSessionId
   * 
   * @param string $asciiSessionId
   */
  public function isAsciiLoggedIn($asciiSessionId) {
  	Service_Debug::setDebug();
  	$objDB = Service_Database::instance();
  	$stmt = "SELECT `logged_in` FROM `session` WHERE `ascii_session_id` = '" . $asciiSessionId . "'";
  	return $objDB->selectSimpleField($stmt);
  }
   
  /**
   * Функция работает с БД
   * Функция выбирает из БД сессию с соответствующим 32-симв идентификатором
   *
   * @param integer $id - ID сеанса
   * @return array - Массив с сессией
   */
  private function _baseGetSessionById($id) {
    Service_Debug::setDebug();
    $objDB = Service_Database::instance();
    $stmt = "SELECT ID_user_session, logged_in, ID_user FROM `session` WHERE ascii_session_id = '$id'";
    return $objDB->select($stmt);
  }

  /**
   * Функция работает с БД
   * Удаляет все сессии, у которых истекло время жизни и текущую сессию согласно ее 32симв. идентификатору
   *
   * @return bool - Удалено или нет
   */
  private function _baseDeleteIncorrectSessionsAndAsciiSess() {
    $objDB = Service_Database::instance();
    //$sql = "DELETE FROM `session` WHERE (ascii_session_id = '". $this->ascii_session_id . "') OR ((now() - created) > $this->sessionLifespan)";
    $sql = "DELETE FROM `session` WHERE (ascii_session_id = '". $this->ascii_session_id . "')";
    return $objDB->query($sql);
  }

  /**
   * Функция работает с БД
   * Удаляет все переменные сессий, которые ссылаются на уже удаленные сессии
   *
   */
  private function _baseDeleteIncorrectSessionsVariables() {
    $objDB = Service_Database::instance();
    $sql = "DELETE FROM `session_variable` WHERE ID_user_session NOT IN (SELECT ID_user_session FROM `session`)";
    $objDB->query($sql);
  }

  /**
   * Функция работает с БД
   * Обновляет время последней активности сессии
   *
   */
  private function _baseUpdatelast_impression() {
    Service_Debug::setDebug();
    $objDB = Service_Database::instance();
    $sql = "UPDATE `session` SET last_impression = now() WHERE ID_user_session = " . $this->ID_user_session;
    $objDB->query($sql);
  }

  /**
   * Функция работает с БД
   * Обновляет время последней активности сессии
   * @return mixed - Массив с пользователем
   */
  private function _baseGetLastImpression() {
    Service_Debug::setDebug();
    $objDB = Service_Database::instance();
    $sql = "SELECT `last_impression` FROM `session` WHERE `ID_user_session` = '" . $this->ID_user_session . "'";
    return $objDB->selectSimpleField($sql);
  }

  /**
   * Функция работает с БД
   * Проверяет, есть ли пользователь с соответствующими login+password
   *
   * @param string $strUsername - Имя пользователя
   * @param string $strMD5Password - Пароль в MD5
   * @return array - Массив с пользователем
   */
  private function _baseIsLogInCorrect($strUsername, $strMD5Password) {
    $objDB = Service_Database::instance();
    $stmt = "SELECT ID_user FROM `user` WHERE nick = '$strUsername' AND md5Pw = '$strMD5Password'";
    return $objDB->select($stmt);
  }

  /**
   * Функция работает с БД
   * Устанавливает необходимые поля у сессии в состояние "Не аутентифицировано"
   *
   */
  private function _baseLogOutSession() {
    $objDB = Service_Database::instance();
    $objDB->update('session', array('logged_in' => 0), array('ID_user_session' => $this->ID_user_session));
  }

  /**
   * Функция работает с БД
   * Устанавливает необходимые поля у сессии в состояние "Аутентифицировано"
   *
   */
  private function _baseLogInSession() {
    $objDB = Service_Database::instance();
    $objDB->update('session', array('logged_in' => true, 'ID_user' => $this->ID_user), array('ID_user_session' => $this->ID_user_session));
  }

  /**
   * Функция работает с БД
   * Устанавливает необходимые поля у сессии в состояние "Аутентифицировано"
   *
   * @param string $idAscii - 32-символьный идентификатор сеанса
   * @param string $struser_agent - Агент пользователя
   * @param bool $isSecondTry - является ли попытка создания второй
   * @return integer - ID сеанса
   */
  private function _baseCreateNewEmptySessionByAscii($idAscii, $struser_agent, $isSecondTry = false) {
    $objDB = Service_Database::instance();
    $objDB->query("INSERT INTO `session` (ascii_session_id, logged_in, ID_user, created, user_agent) VALUES ('" . $idAscii . "','0', null, now(),'" . Service_Escape::absolutelyEscapeString($struser_agent) . "')");
    //Получение истинного идентификатора от только что вставленных данных
    $arResult = $objDB->selectOne("SELECT ID_user_session FROM `session` WHERE ascii_session_id = '" . $idAscii . "'");
    if (empty($arResult['ID_user_session'])) {
    	if ($isSecondTry) return 0;
    	else return $this->_baseCreateNewEmptySessionByAscii($idAscii, $struser_agent, true);
    }
    else return $arResult['ID_user_session'];
  }

  /**
   * Запись значения переменной $nm, относящееся к текущей сессии
   *
   * @param string $nm - Имя параметра
   * @param string $val - Значение параметра
   */
  public function __set($nm, $val) {
    $objDB = Service_Database::instance();
    $strSer = serialize($val);//Сериализуем значение
    $stmt = "SELECT `ID_user_session` FROM `session_variable` WHERE `ID_user_session` = '" . $this->ID_user_session . "' AND `variable_name` = '" . $nm . "'";
    if ($objDB->isRecordExist($stmt)) {
      $stmt = "UPDATE `session_variable` SET `variable_value` = '" . $strSer . "' WHERE `ID_user_session` = '" . $this->ID_user_session . "' AND `variable_name` = '" . $nm . "'";
    }
    else{
      //Вставляем значение в БД для текущей сессии, данного названия переменной $nm
      $stmt = "INSERT INTO `session_variable` (`ID_user_session`,`variable_name`,`variable_value`) VALUES (" . $this->ID_user_session . ",'" . $nm . "','" . $strSer . "')";
    }
    $objDB->query($stmt);
  }

  /**
   * Удаление значения параметра из сессии
   *
   * @param string $nm - Имя параметра
   */
  public function __delete($nm) {
    $objDB = Service_Database::instance();
    $stmt = "DELETE FROM `session_variable` WHERE ID_user_session = " . $this->ID_user_session . " AND variable_name='" . $nm . "'";
    $objDB->query($stmt);
  }

  /**
   * Функция берет переменую из сессии по имени
   *
   * @param string $nm - Имя параметра
   * @return string - Значение параметра
   */
  public function __get($nm) {
    $objDB = Service_Database::instance();
    //Получаем значение переменной $nm, относящееся к текущей сессии
    $arResult = $objDB->select("SELECT variable_value FROM `session_variable` WHERE ID_user_session = " . $this->ID_user_session . " AND variable_name = '" . $nm . "'");
    if (sizeof($arResult)>0) { // Если  есть элементы
      return(unserialize($arResult[sizeof($arResult)-1]["variable_value"]));//возвращаем значение
    }
    else { // Если нет элементов
      return false;
    }
  }

  /**
   * Функция записи массива значений массива переменных, относящихся к текущей сессии
   *
   * @param array $name - массив переменных
   */
  public function __setArray($name) {
    $objDB = Service_Database::instance();
    foreach ($name as $key => $value) {
      $strSer = serialize($value); # Сериализуем значение
      $stmt = "INSERT INTO `session_variable` (`ID_user_session`,`variable_name`,`variable_value`) VALUES (" . $this->ID_user_session . ",'" . $key . "','" . $strSer . "')";
      $objDB->query($stmt);
    }
  }

  /**
   * Получение массва значений переменных
   *
   * @return false/массив значений переменных
   */
  public function __getArray() {
    $objDB = Service_Database::instance();
    $arr = $objDB->select("SELECT variable_value, variable_name FROM `session_variable` WHERE ID_user_session = " . $this->ID_user_session);
    $arResult = array();
    for ($i = 0; $i < sizeof($arr); $i++) {
      $arResult[$arr[$i]['variable_name']] = $arr[$i]['variable_value'];
      if (sizeof($arResult[$arr[$i]['variable_name']]) > 0) {# Если  есть элементы
        $arResult[$arr[$i]['variable_name']] = unserialize($arr[$i]["variable_value"]); # возвращаем значение # [sizeof($arResult)]
      }
    }
    if (isset($arResult) && sizeof($arResult) > 0) return $arResult;
    else {# Если нет элементов
      return false;
    }
  }

  /**
   * Функция удаления записей значений массива переменных
   *
   */
  public function __deleteStr() {
    $objDB = Service_Database::instance();
    $func_list = func_get_args();
    for ($i = 0; $i < sizeof($func_list); $i++) {
      $stmt = 'DELETE FROM `session_variable`
    		WHERE `variable_name` = "' . $func_list[$i] . '"';
      $objDB->query($stmt);
    }
  }
  
 /**
  * Уничтожает лишние сессии
  *
  */
	public static function deleteBadSessions() {
	  Service_Debug::setDebug();
		self::_deleteBadVariables();
		$objDB = Service_Database::instance();
		$stmt = "DELETE FROM `session`
    	WHERE 
    		`last_impression` < DATE_SUB(now(), INTERVAL 15 MINUTE) OR 
    		(`last_impression` IS NULL AND `created` < DATE_SUB(now(), INTERVAL 15 MINUTE))";
		$objDB->query($stmt);
	}

	/**
	 * Удаляет ишние переменные сессий
	 *
	 */
	public static function _deleteBadVariables() {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();
		$stmt = "SELECT `ID_session_variable` FROM `session_variable`
						LEFT JOIN `session` ON `session`.`ID_user_session` = `session_variable`.`ID_user_session`
    				WHERE `session`.`last_impression` < DATE_SUB(now(), INTERVAL 14 MINUTE) OR `session`.`last_impression` IS NULL";
		$arrIds = $objDB->selectSimpleArray($stmt);
		if (!$arrIds) return false;
		$stmt = "DELETE FROM `session_variable`
    				WHERE `ID_session_variable` IN(" . implode(',', $arrIds) . ")";
		$objDB->query($stmt);
		return true;
	}
	
	/**
	 * Сохраняем поисковый запрос по которому пришли
	 */
	public static function registerReferer() {
		$objSession = User_Session::instance();
		if (Service_Function::spiderDetect()) return false; // Не сохраняем ботов
		$userAgent = self::getUserAgent();
		$partner = Service_Escape::requestDataString('partner', 'GET');
		if (!empty($partner)) {
			$objUser = new User_User();
			$objUser->find('first', array('conditions' => "login = '" . $partner . "'"));
			if ($objUser->id) {
				$objPartnerClick = new PartnerClick(array('ID_user' => $objUser->id));
				$objPartnerClick->save();
			}
		} 
		$adWords = isset($_GET['gclid']) ? 1 : 0; 
		if (!empty($_SERVER['HTTP_REFERER'])) {
			$ref = $_SERVER['HTTP_REFERER'];
			$uri = parse_url($ref);
			if (!isset($uri['query'])) $uri['query'] = '';
			$uri['query'] = urldecode($uri['query']);
			$host = isset($uri['host'])? strtolower($uri['host']) : '';
			if (preg_match('#\.' . DOMAIN . '$#', $host)) return false; // Если это наш домен, то не сохраняем переход
			parse_str($a = $uri['query'], $query);
			$refType = 'search';
			if (preg_match('#yandex\.#',$host)) {
				$searchQuery = Service_Function::getValue($host, $query, 'text');
			}
			elseif (preg_match('#google\.#', $host) || $host == 'www.altavista.com' || $host == 'go.mail.ru'
				|| preg_match('#bing\.com$#', $host)|| preg_match('#ask\.com$#', $host) || $host == 'meta.ua') {
				$searchQuery = Service_Function::getValue($host, $query, 'q');
				if (empty($searchQuery)) {
					if (preg_match('#imgurl#', $uri['query'])) $searchQuery = 'IMG';
				}
			}
			elseif ($host == 'sm.aport.ru') {
				$searchQuery = Service_Function::getValue($host, $query, 'r');
			}
			elseif ($host == 'nova.rambler.ru' || preg_match('#search\.qip\.ru$#', $host)) {
				if (isset($query['query'])) $searchQuery = $query['query'];
				else $searchQuery = Service_Function::getValue($host, $query, 'words');
			}
			elseif ($host == 'go.km.ru') {
				$searchQuery = Service_Function::getValue($host, $query, 'sq');
			}
			elseif ($host == 'search.yahoo.com') {
				$searchQuery = Service_Function::getValue($host, $query, 'p');
			}
			elseif (preg_match('#nigma\.#', $host)) {
				$searchQuery = Service_Function::getValue($host, $query, 's');
			}
			else {
				$searchQuery = $host;
				$refType = 'link';
			}
			if ($host . '/' != SITE_URL) {
				if (isset($query['utm_term'])) $refType = 'ad';
				if ($host == 'googleads.g.doubleclick.net') $refType = 'ad_media';
				$objDB = Service_Database::instance();
				$searchId = $objDB->insertAutoincrement('search_query', array(
					'host' => Service_Escape::absolutelyEscapeString($host),
					'query' => Service_Escape::absolutelyEscapeString($searchQuery),
					'url' => Service_Escape::absolutelyEscapeString($_SERVER['REQUEST_URI']),
					'ref' => Service_Escape::absolutelyEscapeString($ref),
					'ref_type' => $refType,
					'ip' => self::getIP(),
					'ID_session' => $objSession->getSessionIdentifier(),
					'user_agent' => Service_Escape::absolutelyEscapeString($userAgent),
					'created_at' => Service_Date::gLocalTime2BD(),
					'is_google_adwords' => $adWords,
					'partner' => $partner,
				));
				if (empty($_COOKIE['searchId'])) {
					$time = preg_match('#Chrome/[19|20|21|22|23|24|25|26|27]#', $userAgent) ? time() + 3600 * 6 : null;
					setcookie('searchId', $searchId, $time, W_ABSPATH, DOMAIN);
				}
				return true;
			}
		}
		else {
			if ($_SERVER['REQUEST_URI'] == '/server-status?auto') return false;
			if ($_SERVER['REQUEST_URI'] == '*') return false;
			if ($_SERVER['REQUEST_URI'] == '/favicon.ico') return false;
			$objDB = Service_Database::instance();
			$searchId = $objDB->insertAutoincrement('search_query', array(
				'url' => Service_Escape::absolutelyEscapeString($_SERVER['REQUEST_URI']),
				'ref_type' => 'straight',
				'ip' => self::getIP(),
				'ID_session' => $objSession->getSessionIdentifier(),
				'user_agent' => Service_Escape::absolutelyEscapeString($userAgent),			
				'created_at' => Service_Date::gLocalTime2BD(),
				'is_google_adwords' => $adWords,
				'partner' => $partner,
			));
			if (empty($_COOKIE['searchId'])) {
				$time = preg_match('#Chrome/[19|20|21|22|23|24|25|26|27]#', $userAgent) ? time() + 3600 * 6 : null;
				setcookie('searchId', $searchId, $time, W_ABSPATH, DOMAIN);
				
			}
			return true;			
		}
		return false;
	}
	
	/**
	 * Метод получает количество обращений пользователем за последние секунды
	 *
	 * @param int $seconds
	 * @return int
	 */
	public static function getTreatmentsAmountByIp($seconds) {
		$ip = self::getIP();
		if ($ip != 'unknown') {
			$objDB = Service_Database::instance();
			$stmt = "SELECT COUNT(`ip`) FROM `ip_check`
                     WHERE `ip` = '" . $ip . "' AND `created` > DATE_SUB(now(), INTERVAL " . intval($seconds) . " SECOND);";
			return $objDB->selectSimpleField($stmt);
		}
		else return 0;
  }
	
	/**
	 * Метод вставляет информацию о новом обращении
	 *
	 */
	public static function insertNewTreatment() {
		$ip = self::getIP();
		if ($ip != 'unknown' && !preg_match('#ajax/hotel/check_available#', $_SERVER['REQUEST_URI'])) {
			$objDB = Service_Database::instance();
			$stmt = "INSERT INTO `ip_check` (`ip`, `created`) VALUES ('" . $ip . "', now());";
			$objDB->query($stmt);
		}
	}
	
	/**
	 * Метод очищает таблицу обращений к серверу
	 *
	 * @param int $seconds
	 * @return int
	 */
	public static function clearTreatments($seconds) {
		$objDB = Service_Database::instance();
		$stmt = "DELETE FROM `ip_check`
             WHERE `created` < DATE_SUB(now(), INTERVAL " . intval($seconds) . " SECOND);";
		return $objDB->query($stmt);
	}

	/**
	 * Получаем IP
	 *
	 * @return string - IP-адрес 
	 */
	public static function getIP() {
	  if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) $ip = getenv("HTTP_CLIENT_IP");
	  else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) $ip = getenv("HTTP_X_FORWARDED_FOR");
	  else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) $ip = getenv("REMOTE_ADDR");
	  else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) $ip = $_SERVER['REMOTE_ADDR'];
	  else $ip = "unknown";
	  return $ip;
	} // GetIP

	/**
	 * Добавляет в статистику инфу о заблокированном IP и блочит его
	 * 
	 * @param string $ip
	 */
	public static function addToBadIp($ip) {
		$fp = fopen(ABSPATH . '../bad_ips.php', 'a+');
		fwrite($fp, '<?php $badIps[]="' . $ip . '";?>');
		fclose($fp);
		$objDB = Service_Database::instance();	
		$objDB->insert('bad_ip', array('ip' => $ip, 'created' => Service_Date::gLocalTime2BD()));	
	}
	
	/**
	 * Возвращает информацию о браузере клиента
	 * 
	 * @return string - строка с информацие о клиенте
	 */
	public static function getUserAgent() {
		Service_Debug::setDebug();
		return Service_Escape::absolutelyEscapeString(Service_Function::getValue('', $_SERVER, 'HTTP_USER_AGENT'));
	}
}
?>